﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Expression.Interactivity.Core;
using Microsoft.Expression.Interactivity.Layout;
using QDP.Platform.ObjService;
using QDP.Platform.Silverlight.Aware;
namespace QDP.Platform.Silverlight.Controls
{
    /// <summary>表示一个组件窗口控件，它将为UserControl形式的组件统一增加边框。</summary>
    [TemplatePart(Name = KEY_PART_ContentPresenter, Type = typeof(ContentPresenter))
    , TemplatePart(Name = KEY_PART_Thumb, Type = typeof(Border))
    , TemplatePart(Name = KEY_PART_TitleBlock, Type = typeof(TextBlock))
    , TemplatePart(Name = KEY_PART_DescBlock, Type = typeof(TextBlock))
    , TemplatePart(Name = KEY_PART_TitleIcon, Type = typeof(Image))
    , TemplatePart(Name = KEY_PART_CloseButton, Type = typeof(Button))
    , TemplatePart(Name = KEY_PART_RefreshButton, Type = typeof(Button))
    , TemplatePart(Name = KEY_PART_MinimizeButton, Type = typeof(Button))
    , TemplatePart(Name = KEY_PART_MaxsizeButton, Type = typeof(Button))
    , TemplatePart(Name = KEY_PART_ResizeButton, Type = typeof(Button))]
    [TemplateVisualState(Name = "Minimizaed", GroupName = "CommonStates")]
    [TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Maximizable, Desc = "表示组件是否允许最大化"
        , DefaultValue = "false")]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Minimizable, Desc = "表示组件是否允许最小化"
        , DefaultValue = KEY_TRUE)]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Width, Desc = "表示组件宽度")]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Height, Desc = "表示组件高度")]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Left, Desc = "表示组件与左侧边框的距离")]
    [WidgetMeta(Category = NParams.CategoryStyle
        , Key = KEY_Top, Desc = "表示组件与顶部边框的距离")]
    [WidgetMeta(Category = NParams.CategoryLayout
        , Key = KEY_Dock, Desc = "表示组件在父级容器中停靠的位置"
        , EnumValues = KEY_Dock_Right + "," + KEY_Dock_Center + "," + KEY_Dock_Full)]
    public class WidgetControl : Control
    {
        const string KEY_PART_ContentPresenter = "PART_ContentPresenter";
        const string KEY_PART_Thumb = "PART_Thumb";
        const string KEY_PART_TitleBlock = "PART_TitleBlock";
        const string KEY_PART_DescBlock = "PART_DescBlock";
        const string KEY_PART_TitleIcon = "PART_TitleIcon";
        const string KEY_PART_CloseButton = "PART_CloseButton";
        const string KEY_PART_RefreshButton = "PART_RefreshButton";
        const string KEY_PART_MinimizeButton = "PART_MinimizeButton";
        const string KEY_PART_MaxsizeButton = "PART_MaxsizeButton";
        const string KEY_PART_ResizeButton = "PART_ResizeButton";

        const string KEY_Maximizable = "Maximizable";
        const string KEY_Minimizable = "Minimizable";
        const string KEY_Width = "Width";
        const string KEY_Height = "Height";
        const string KEY_Left = "Left";
        const string KEY_Top = "Top";
        const string KEY_Dock = "Dock";
        const string KEY_Dock_Right = "right";
        const string KEY_Dock_Center = "center";
        const string KEY_Dock_Full = "full";
        const string KEY_TRUE = "true";

        /// <summary>获取或设置组件中的内容控件。</summary>
        public UserControl Child { get; set; }
        /// <summary>获取或设置组件的描述内容。</summary>
        public Widget Widget { get; set; }
        public NavigationBase Navigation
        {
            get
            {
                if (Widget == null || Widget.Navigation == null) return null;
                return Widget.Navigation;
            }
        }
        private PartElement Part
        {
            get
            {
                if (Widget == null || Widget.PartElement == null) return null;
                return Widget.PartElement;
            }
        }
        /// <summary>获取组件的缩略图。</summary>
        public ImageSource ThumbnailImage { get; private set; }
        private Border PART_Thumb;
        private ContentPresenter PART_ContentPresenter;
        private Button PART_CloseButton;
        private Button PART_ResizeButton;
        private Button PART_MaxsizeButton;
        private Button PART_MinimizeButton;
        private Button PART_RefreshButton;
        private TextBlock PART_TitleBlock;
        private TextBlock PART_DescBlock;
        private Image PART_TitleIcon;

        double top, left, width, height;
        double bx, by;
        private bool IsCanDrag = true;

        /// <summary>以默认参数构造一个组件窗口控件对象的示例。</summary>
        public WidgetControl()
        {
            this.DefaultStyleKey = typeof(WidgetControl);
            this.Loaded += new RoutedEventHandler(WidgetControl_Loaded);
            behavior.DragFinished += new MouseEventHandler(behavior_DragFinished);
        }

        void WidgetControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.OnShow();
        }
        // 重写窗口获得焦点事件，主要是用来激活窗口。
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            base.OnGotFocus(e);
            this.OnActive();
        }
        // 重写鼠标左键点击事件，主要是用来激活窗口。
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            //this.Focus();
            this.OnActive();
        }

        private bool hasMaximizeButton = false;
        /// <summary>刷新系统按钮可视化状态。</summary>
        private void RefreshButtonVisable()
        {
            if (this.PART_MaxsizeButton != null)
            {
                if (Widget.Configs.ContainsKey(KEY_Maximizable) == true
                    && Widget.Configs[KEY_Maximizable].ToLower() == KEY_TRUE)
                {
                    hasMaximizeButton = true;
                    this.PART_MaxsizeButton.Command = new ActionCommand(this.OnMaximize);
                }
                else
                {
                    this.PART_MaxsizeButton.Visibility = System.Windows.Visibility.Collapsed;
                }
            }

            if (this.PART_MinimizeButton != null)
            {
                if (Widget.Configs.ContainsKey(KEY_Minimizable) == false
                    || Widget.Configs[KEY_Minimizable].ToLower() == KEY_TRUE)
                {
                    this.PART_MinimizeButton.Command = new ActionCommand(this.OnMinimize);
                }
                else
                {
                    this.PART_MinimizeButton.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
            if (this.PART_ResizeButton != null)
            {
                this.PART_ResizeButton.Visibility = System.Windows.Visibility.Collapsed;
                this.PART_ResizeButton.Command = new ActionCommand(this.OnRestore);
            }
            // 处理刷新按钮状态及指令
            if (PART_RefreshButton != null)
            {
                if (Child is IRefreshAware || (Child != null && Child.DataContext is IRefreshAware))
                {
                    PART_RefreshButton.Command = new ActionCommand(this.OnRefresh);
                }
                else
                {
                    PART_RefreshButton.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }
        /// <summary>刷新窗口内容布局。</summary>
        private void RefreshContent()
        {
            if (this.PART_ContentPresenter != null)
            {
                PART_ContentPresenter.Content = Child;

                // 设置窗口宽度
                double width = 0;
                if (Widget.Configs.ContainsKey(KEY_Width) == false
                    || double.TryParse(Widget.Configs[KEY_Width], out width) == false
                    || width < 0)
                {
                    width = Child.Width;
                }
                if (IsMaximized)
                    PART_ContentPresenter.Width = this.Width;
                else
                    PART_ContentPresenter.Width = width;

                // 设置窗口高度
                double height = 0;
                if (Widget.Configs.ContainsKey(KEY_Height) == false
                    || double.TryParse(Widget.Configs[KEY_Height], out height) == false
                    || height < 0)
                {
                    height = Child.Height;
                }
                if (IsMaximized)
                    PART_ContentPresenter.Height = this.Height - 60;
                else
                    PART_ContentPresenter.Height = height;
                // 处理窗口停靠
                double left = -1;
                double top = -1;
                if (Widget.Configs.ContainsKey(KEY_Dock))
                {
                    string dock = Widget.Configs[KEY_Dock].ToLower();
                    switch (dock)
                    {
                        case KEY_Dock_Right:
                            if (double.IsNaN(width))
                                left = Q.MainPage.Root.ActualWidth - 10;
                            else
                                left = Q.MainPage.Root.ActualWidth - width - 10;
                            top = 10;
                            break;
                        case KEY_Dock_Center:
                            if (double.IsNaN(width))
                                left = (Q.MainPage.Root.ActualWidth - 10) / 2;
                            else
                                left = (Q.MainPage.Root.ActualWidth - width - 10) / 2;

                            if (double.IsNaN(height))
                                top = (Q.MainPage.Root.ActualHeight - 10) / 2;
                            else
                                top = (Q.MainPage.Root.ActualHeight - height - 10) / 2;
                            break;
                        case KEY_Dock_Full:
                            left = 0;
                            top = 0;
                            // 设置窗口不可拖拽
                            IsCanDrag = false;
                            // 30为任务栏高度，24为窗口标题栏高度
                            PART_ContentPresenter.Height = Q.MainPage.Root.ActualHeight - 30 - 24;
                            PART_ContentPresenter.Width = Q.MainPage.Root.ActualWidth;
                            break;
                    }
                }
                if (left == -1) // left=-1表示未设置,可以读取left参数设置；
                {
                    // 处理窗体居左
                    if (Widget.Configs.ContainsKey(KEY_Left) == false
                        || double.TryParse(Widget.Configs[KEY_Left], out left) == false)
                    {
                        left = Canvas.GetLeft(this) == 0 ? Canvas.GetLeft(Child) : Canvas.GetLeft(this);
                    }
                }
                if (double.IsNaN(left) == false)
                {
                    left = Math.Round(left);
                    Canvas.SetLeft(this, left);
                }
                // 处理窗体居顶
                if (top == -1) // top=-1表示未设置，可以读取top参数设置；
                {
                    if (Widget.Configs.ContainsKey(KEY_Top) == false
                        || double.TryParse(Widget.Configs[KEY_Top], out top) == false)
                    {
                        top = Canvas.GetTop(this) == 0 ? Canvas.GetTop(Child) : Canvas.GetTop(this);
                    }
                }
                if (double.IsNaN(top) == false)
                {
                    top = Math.Round(top);
                    Canvas.SetTop(this, top);
                }
            }
        }
        /// <summary>重写控件样式</summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.PART_ContentPresenter = base.GetTemplateChild(KEY_PART_ContentPresenter) as ContentPresenter;
            this.PART_Thumb = base.GetTemplateChild(KEY_PART_Thumb) as Border;
            this.PART_TitleBlock = base.GetTemplateChild(KEY_PART_TitleBlock) as TextBlock;
            this.PART_CloseButton = base.GetTemplateChild(KEY_PART_CloseButton) as Button;
            this.PART_DescBlock = base.GetTemplateChild(KEY_PART_DescBlock) as TextBlock;
            this.PART_TitleIcon = base.GetTemplateChild(KEY_PART_TitleIcon) as Image;
            this.PART_MinimizeButton = base.GetTemplateChild(KEY_PART_MinimizeButton) as Button;
            this.PART_MaxsizeButton = base.GetTemplateChild(KEY_PART_MaxsizeButton) as Button;
            this.PART_ResizeButton = base.GetTemplateChild(KEY_PART_ResizeButton) as Button;
            this.PART_RefreshButton = base.GetTemplateChild(KEY_PART_RefreshButton) as Button;

            if (Widget == null || Child == null) return;

            if (this.PART_CloseButton != null)
            {
                this.PART_CloseButton.Command = new ActionCommand(this.OnClose);
            }

            this.RefreshButtonVisable();
            this.RefreshContent();

            #region 处理 PART_TitleBlock
            if (this.PART_TitleBlock != null)
            {
                //#if DEBUG
                //                this.PART_TitleBlock.Text = Contract.Navigation.Caption + " | " + (Contract.Navigation as NavUISLXap).Type;
                //#else
                this.PART_TitleBlock.Text = Widget.Navigation.Caption;
                //#endif
            }
            #endregion //#region 处理 PART_TitleBlock

            #region 处理 PART_TitleIcon
            if (this.PART_TitleIcon != null)
            {
                this.PART_TitleIcon.SetBinding(Image.SourceProperty
                    , new Binding()
                    {
                        Source = Navigation,
                        Path = new PropertyPath("ImageUrl1")
                    });
            }
            #endregion //#region 处理 PART_TitleIcon

            #region 处理 PART_DescBlock
            if (this.PART_DescBlock != null)
            {
                this.PART_DescBlock.SetBinding(TextBlock.TextProperty
                    , new Binding()
                    {
                        Source = Navigation,
                        Path = new PropertyPath("Description"),
                        TargetNullValue = "Description"
                    });
            }
            #endregion //#region 处理 PART_DescBlock

            #region 处理 PART_Thumb
            if (this.PART_Thumb != null)
            {
                this.PART_Thumb.MouseEnter += (sender, eventArgs) =>
                {
                    // 判断当前状态是否可以执行拖拽操作。
                    if (IsCanDrag == false || IsMaximized) return;
                    this.AttachMouseDrag();
                };
                this.PART_Thumb.MouseLeave += (sender, eventArgs) =>
                {
                    // 判断当前状态是否可以执行拖拽操作。
                    if (IsCanDrag == false || IsMaximized) return;
                    this.DetachMouseDrag();
                };
            }
            #endregion //#region 处理 PART_Thumb
        }

        #region 关于 窗口事件
        private void InitThumbnailImage()
        {
            FrameworkElement icon = this;

            int width = double.IsNaN(icon.Width) ? (int)icon.ActualWidth : (int)icon.Width;
            int height = double.IsNaN(icon.Height) ? (int)icon.ActualHeight : (int)icon.Height;

            ScaleTransform transform = null;

            WriteableBitmap bitmap = new WriteableBitmap(width, height);
            bitmap.Render(icon, transform);
            bitmap.Invalidate();

            ThumbnailImage = bitmap;
        }
        // 激活窗口
        private void OnActive()
        {
            if (Part != null)
            {
                Part.Active();
            }
        }
        // 关闭窗口
        public void OnClose()
        {
            if (Part != null && Part.IsShowed == true)
            {
                Part.Close();
                Q.EventMonitor.ResumeClosedEvent(Child, Navigation.Code);
            }
        }
        // 显示窗口
        private void OnShow()
        {
            Q.EventMonitor.ResumeShowedEvent(Child, Navigation.Code);
        }
        /// <summary>最小化窗口</summary>
        private void OnMinimize()
        {
            if (Q.EventMonitor.ResumeMinimizingEvent(Child, Navigation.Code) == false)
            {
                this.ChangeButtonState(3);
                if (Parent != null)
                {
                    this.InitThumbnailImage();
                    Part.WidgetParent.Children.Remove(this);
                }
                Q.EventMonitor.ResumeMinimizedEvent(Child, Navigation.Code);
            }
        }
        /// <summary>最大化窗口</summary>
        private void OnMaximize()
        {
            if (Parent != null)
            {
                top = Canvas.GetTop(this);
                left = Canvas.GetLeft(this);
                by = behavior.Y;
                bx = behavior.X;
                width = this.ActualWidth;
                height = this.ActualHeight;

                Width = Q.MainPage.Root.ActualWidth;
                Height = Q.MainPage.Root.ActualHeight;
                Canvas.SetTop(this, double.IsNaN(by) ? 0 : -by);
                Canvas.SetLeft(this, double.IsNaN(bx) ? 0 : -bx);
                behavior.X = 0;
                behavior.Y = 0;
            }
            this.ChangeButtonState(2);
        }
        /// <summary>恢复窗口大小</summary>
        public void OnRestore()
        {
            if (Q.EventMonitor.ResumeRestoringEvent(Child, Navigation.Code) == false)
            {
                if (IsMinimized)
                {
                    Part.WidgetParent.Children.Add(this);
                }
                if (IsMaximized)
                {
                    Width = width;
                    Height = height;
                    Canvas.SetTop(this, top);
                    Canvas.SetLeft(this, left);
                    behavior.X = bx;
                    behavior.Y = by;
                }
                this.ChangeButtonState(1);
                Q.EventMonitor.ResumeResizedEvent(Child, Navigation.Code);
            }
        }
        /// <summary>刷新窗口内容：调用窗口刷新方法。</summary>
        private void OnRefresh()
        {
            if (Child is IRefreshAware)
                (Child as IRefreshAware).Refresh();
            else if (Child != null && Child.DataContext is IRefreshAware)
            {
                (Child.DataContext as IRefreshAware).Refresh();
            }
        }

        #endregion //#region 关于 窗口事件

        #region 处理 窗口大小变更
        /// <summary>获取或设置窗口是否处于最大化状态</summary>
        public bool IsMaximized { get; set; }
        /// <summary>获取或设置窗口是否处于最小化状态</summary>
        public bool IsMinimized { get; set; }

        /// <summary>最小化之前是否为最大化状态。</summary>
        private bool beforeMinimizeIsMaximize = false;
        private void ChangeButtonState(int type)
        {
            if (1 == type)
            {
                if (IsMinimized == false)
                {
                    beforeMinimizeIsMaximize = false;
                }
                if (this.PART_MinimizeButton != null)
                    this.PART_MinimizeButton.Visibility = Visibility.Visible;

                IsMinimized = false;

                if (hasMaximizeButton)
                {
                    if (this.PART_MaxsizeButton != null)
                        this.PART_MaxsizeButton.Visibility = beforeMinimizeIsMaximize
                            ? Visibility.Collapsed
                            : Visibility.Visible;
                    if (this.PART_ResizeButton != null)
                        this.PART_ResizeButton.Visibility = beforeMinimizeIsMaximize
                            ? Visibility.Visible
                            : Visibility.Collapsed;
                }

                IsMaximized = beforeMinimizeIsMaximize;
                if (this.PART_CloseButton != null)
                    this.PART_CloseButton.Visibility = Visibility.Visible;
                this.RefreshContent();
            }
            else if (2 == type)// 最大化窗口
            {
                IsMaximized = true;
                IsMinimized = false;

                if (Widget.Configs.ContainsKey("Minimizable") == false
                    || Widget.Configs["Minimizable"].ToLower() == "true")
                {
                    if (this.PART_MinimizeButton != null)
                        this.PART_MinimizeButton.Visibility = Visibility.Visible;
                }
                if (hasMaximizeButton)
                {
                    if (this.PART_ResizeButton != null)
                        this.PART_ResizeButton.Visibility = Visibility.Visible;
                    if (this.PART_MaxsizeButton != null)
                        this.PART_MaxsizeButton.Visibility = Visibility.Collapsed;
                }
                if (this.PART_CloseButton != null)
                    this.PART_CloseButton.Visibility = Visibility.Visible;
                this.RefreshContent();
            }
            else if (3 == type)// 最小化窗口
            {
                if (IsMaximized)
                    beforeMinimizeIsMaximize = true;
                else
                    beforeMinimizeIsMaximize = false;

                IsMinimized = true;
                IsMaximized = false;

                if (this.PART_MinimizeButton != null)
                    this.PART_MinimizeButton.Visibility = Visibility.Collapsed;

                if (this.PART_CloseButton != null)
                    this.PART_CloseButton.Visibility = Visibility.Collapsed;
            }
        }
        #endregion //#region 处理 窗口大小变更

        #region 处理窗口拖拽相关内容

        MouseDragElementBehavior behavior = new MouseDragElementBehavior() { ConstrainToParentBounds = false };
        // 处理窗口超出可视范围；
        void behavior_DragFinished(object sender, MouseEventArgs e)
        {
            if (behavior.Y > Part.WidgetParent.ActualHeight - 50)
                behavior.Y = Part.WidgetParent.ActualHeight - this.ActualHeight;
            if (behavior.Y < -10)
                behavior.Y = 0;
        }
        private void AttachMouseDrag()
        {
            try
            {
                behavior.Attach(this);
            }
            catch { }
        }
        private void DetachMouseDrag()
        {
            try
            {
                behavior.Detach();
            }
            catch { }
        }

        #endregion //#region 处理窗口拖拽相关内容
    }
}